package ventureco.communication;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;


public class ThreadServer extends Thread{

	private ServerSocket serverSock = null;
	public static HashMap<Integer, Integer> ipAddresses = new HashMap<Integer, Integer>();
	
    public ThreadServer(int serverPort) {
	try {
	    serverSock = new ServerSocket(serverPort);
//	    System.out.println("server olustu");
 	}
 	catch (IOException e){
	    e.printStackTrace(System.err);
 	}
    }
    
   
    @SuppressWarnings("unchecked")
	public void handleConnection(InputStream sockInput, OutputStream sockOutput) {
	while(true) {
	    byte[] buf=new byte[1024];
	    int bytes_read = 0;
	    try {
		// This call to read() will wait forever, until the
		// program on the other side either sends some data,
		// or closes the socket.
	    	//System.err.println("About to start reading from socket.");
	    	
		bytes_read = sockInput.read(buf, 0, buf.length);
//		System.out.println("okundu");
		
		// If the socket is closed, sockInput.read() will return -1.
		if(bytes_read < 0) {
		    System.err.println("Tried to read from socket, read() returned < 0,  Closing socket.");
		    return;
		}
		
		
		
		if(buf[0]==0) { 
			
//			System.out.println("EFEFEFEFEFE");
			byte[] purebuf = new byte[buf.length - 1];
			System.arraycopy(buf, 1, purebuf, 0, buf.length - 1);
		
		ByteArrayInputStream baos = new ByteArrayInputStream(purebuf);

		ObjectInputStream objin;
	
			objin = new ObjectInputStream(baos);
			ipAddresses = (HashMap<Integer, Integer>) objin.readObject();
			System.out.println("Updaten Agent Address Lists is :");
			for(int i=0;i<ipAddresses.size();i++)
				System.out.println(ipAddresses.get(i));
			System.out.println("---------------------------------------");
	
		}
		else if(buf[0] == 1)
		{
//			System.out.println("EFEFE222");
			byte[] purebuf = new byte[buf.length - 1];
			System.arraycopy(buf, 1, purebuf, 0, buf.length - 1);
			
			AgentMessage incomingMessage = new AgentMessage();
			
			ByteArrayInputStream baos = new ByteArrayInputStream(purebuf);
			ObjectInputStream objin;
			objin = new ObjectInputStream(baos);
			incomingMessage = (AgentMessage) objin.readObject();
			
			if(incomingMessage.allArea) {
				
				/* 
				 * METHOD FOR MESSAGE TYPE 1
				 * 
				 * ALL AREA HAS BEEN SCANNED
				 * 
				 */
				System.out.println("Received message type is : ALL AREA HAS BEEN SCANNED");
			}
			
			else if(incomingMessage.newTasks) {
				/* 
				 * METHOD FOR MESSAGE TYPE 2
				 * 
				 * NEW TASKS ARE READY
				 * 
				 */
				System.out.println("Received message type is : NEW TASKS ARE READY");

			}
			
			else if(incomingMessage.taskIsTaken) {
				/* 
				 * METHOD FOR MESSAGE TYPE 3
				 * 
				 * TASK # IS TAKEN
				 * 
				 */
				System.out.println("Received message type is : TASK # IS TAKEN");
			}
			
			else if(incomingMessage.taskIsFailed) {
				/* 
				 * METHOD FOR MESSAGE TYPE 4
				 * 
				 * TASK # IS FAILED
				 * 
				 */
				System.out.println("Received message type is : TASK # IS FAILED DUE TO LOW BATTERY");
			}
			
			else if(incomingMessage.taskComplated) {
				/* 
				 * METHOD FOR MESSAGE TYPE 5
				 * 
				 * TASK # IS COMPLETED
				 * 
				 */
				System.out.println("Received message type is : TASK # IS COMPLETED");
			}
			
			//String incoming = new String(purebuf,0,bytes_read-1);
		}
		
		
		
//		System.out.println("Received "+bytes_read
//				   +" bytes, data="
//				   +(new String(buf, 0, bytes_read)));
		//sockOutput.write(buf, 0, bytes_read);
				sockOutput.flush();
	    }
	    catch (Exception e){
		System.err.println("Exception reading from/writing to socket, e="+e);
		e.printStackTrace(System.err);
		
	    }
	    return;
	}

    }

    public void waitForConnections() {
	Socket sock = null;
	InputStream sockInput = null;
	OutputStream sockOutput = null;
	while (true) {
	    try {
		// This method call, accept(), blocks and waits
		// (forever if necessary) until some other program
		// opens a socket connection to our server. 
		sock = serverSock.accept();
		System.err.println("Have accepted new socket.");

		// From this point on, no new socket connections can
		// be made to our server until we call accept() again.

		sockInput = sock.getInputStream();
		sockOutput = sock.getOutputStream();
	    }
	    catch (IOException e){
		e.printStackTrace(System.err);
	    }

	    // Do something with the socket - read bytes from the
	    // socket and write them back to the socket until the
	    // other side closes the connection.
	    handleConnection(sockInput, sockOutput);

	    // Now we close the socket.
	    try {
		//System.err.println("Closing socket.");
		sock.close();
	    }
	    catch (Exception e){
		System.err.println("Exception while closing socket.");
		e.printStackTrace(System.err);
	    }

	    System.err.println("Finished with socket, waiting for next connection.");
	}
 }


	@Override
	public void run() {
		// TODO Auto-generated method stub
		waitForConnections();
	}
}
